﻿namespace Mercury.ParticleEngine.StateManagers
{
    using System;
    using System.Diagnostics.Contracts;

    public class InMemoryStateManager : IStateManager
    {
        private readonly ParticleState[] _stateBuffer;

        public Single ReleaseSpeed { get; set; }

        public InMemoryStateManager(Int32 capacity)
        {
            Contract.Requires<ArgumentOutOfRangeException>(capacity > 0);
            Contract.Requires<ArgumentException>(capacity.IsPerfectSquare());

            _stateBuffer = new ParticleState[capacity];
        }

        public unsafe void InitializeState(ref MetaParticleIterator iterator)
        {
            var meta = iterator.First;

            fixed (ParticleState* stateBuffer = _stateBuffer)
            {
                do
                {
                    var state = stateBuffer + meta->Index;

                    state->Position = meta->ReleaseContext.WorldPosition;
                    state->Speed    = meta->ReleaseContext.Direction * ReleaseSpeed;
                }
                while (iterator.MoveNext(&meta));
            }
        }

        public unsafe void UpdateState(ref MetaParticleIterator iterator)
        {
            var meta = iterator.First;

            fixed (ParticleState* stateBuffer = _stateBuffer)
            {
                do
                {
                    var state = stateBuffer + meta->Index;

                    state->Position = state->Position.Translate(state->Speed);
                }
                while (iterator.MoveNext(&meta));
            }
        }

        public unsafe void Render(ref MetaParticleIterator iterator)
        {
            var meta = iterator.First;

            fixed (ParticleState* stateBuffer = _stateBuffer)
            {
                do
                {
                    var state = stateBuffer + meta->Index;

                    Console.WriteLine(state->Position);
                }
                while (iterator.MoveNext(&meta));
            }
        }

        private struct ParticleState
        {
            public Coordinate Position;
            public Vector Speed;
        }
    }
}